package person.wend.javalearnexample.util;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class ArraysExample {

    public static void main(String[] args) {
        numberSort();
        objectSort();
        ParallelSort();
        binarySearch();
        equalsTest();
        parallelPrefixTest();
        fillTest();
        copyOfTest();
        asList();
        hashCodeTest();
        toStringTest();
        setAllExample();
        spliteratorExample();
        streamTest();
        compareTest();
        missMatchTest();
    }

    public static void missMatchTest() {
        // 创建两个整型数组进行比较
        int[] array1 = {1, 2, 3, 4, 5};
        int[] array2 = {1, 2, 0, 4, 5};

        // 使用 mismatch 查找第一个不匹配的位置
        int index = Arrays.mismatch(array1, array2);
        System.out.println("First mismatch at index: " + index); // 输出 2，因为第三个元素不同

        // 如果两个数组完全相同
        int[] array3 = {1, 2, 3, 4, 5};
        index = Arrays.mismatch(array1, array3);
        System.out.println("First mismatch at index: " + index); // 输出 -1，表示没有不匹配的地方
    }

    public static void compareTest() {
        int[] array1 = {1, 2, 3};
        int[] array2 = {1, 2, 4};
        int result = Arrays.compare(array1, array2);
        System.out.println("比较结果: " + result);

        // 示例 2 compareUnsigned
        int result2 = Arrays.compareUnsigned(array1, array2);
        System.out.println("比较结果（无符号比较）: " + result2);

    }

    public static void streamTest() {
        String[] stringArray = {"apple", "banana", "cherry", "date"};
        Stream<String> stream = Arrays.stream(stringArray);
        stream.filter(str -> str.length() > 5)
                .map(String::toUpperCase)
                .forEach(System.out::println);
    }

    public static void spliteratorExample() {
        // 创建一个整数数组
        int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

        // 使用 spliterator() 方法创建一个 Spliterator 对象
        java.util.Spliterator<Integer> spliterator = Arrays.spliterator(numbers);

        // 使用 tryAdvance() 方法遍历 Spliterator
        System.out.println("Traversing the Spliterator:");
        spliterator.tryAdvance(System.out::println);

        // 使用 forEachRemaining() 方法遍历剩余元素
        spliterator.forEachRemaining(System.out::println);

        // 使用 trySplit() 方法拆分 Spliterator
        java.util.Spliterator<Integer> split = spliterator.trySplit();

        // 使用 tryAdvance() 方法遍历拆分后的 Spliterator
        System.out.println("Traversing the split Spliterator:");
        if (split != null) {
            split.tryAdvance(System.out::println);
            split.forEachRemaining(System.out::println);
        }

        // 使用 estimateSize() 方法获取剩余元素数量
        System.out.println("Remaining elements in the original Spliterator: " + spliterator.estimateSize());
        // 使用 characteristics() 方法获取 Spliterator 的特性
        System.out.println("Characteristics of the original Spliterator: " + spliterator.characteristics());
        // 使用 getExactSizeIfKnown() 方法获取确切元素数量
        System.out.println("Exact size of the original Spliterator: " + spliterator.getExactSizeIfKnown());
        // 使用 hasCharacteristics() 方法检查 Spliterator 的特性
        System.out.println("The original Spliterator is SIZED: " + spliterator.hasCharacteristics(java.util.Spliterator.SIZED));
    }

    public static void setAllExample() {
        // 使用 setAll 初始化一个整型数组，每个元素是其索引的平方
        int[] squares = new int[5];
        Arrays.setAll(squares, i -> i * i);
        System.out.println("Squares: " + Arrays.toString(squares)); // [0, 1, 4, 9, 16]

        // 使用 setAll 初始化一个字符串数组，每个元素是其索引的字符表示
        String[] indexedStrings = new String[3];
        Arrays.setAll(indexedStrings, Integer::toString);
        System.out.println("Indexed strings: " + Arrays.toString(indexedStrings)); // [0, 1, 2]

        // 使用 parallelSetAll 并行初始化一个大整型数组，每个元素是其索引的立方
        int[] cubes = new int[1000000];
        Arrays.parallelSetAll(cubes, i -> i * i * i);

        // 打印前五个元素作为示例
        System.out.println("First five cubes: " + Arrays.toString(Arrays.copyOfRange(cubes, 0, 5))); // [0, 1, 8, 27, 64]

        // 对于对象数组，可以使用更复杂的生成逻辑
        String[] complexObjects = new String[10];
        Arrays.parallelSetAll(complexObjects, i -> "Object-" + i);
        System.out.println("Complex objects: " + Arrays.toString(complexObjects));
    }

    public static void toStringTest() {
        int[] array = {1, 2, 3, 4, 5};
        String arrayString = Arrays.toString(array);
        System.out.println(arrayString); // 输出: [1, 2, 3, 4, 5]

        int[][] deepArray = {{1, 2}, {3, 4, 5}, {6}};
        String deepArrayString = Arrays.deepToString(deepArray);
        System.out.println(deepArrayString); // 输出: [[1, 2], [3, 4, 5], [6]]
    }

    public static void hashCodeTest() {
        // 计算字符串数组的哈希码
        String[] array1 = {"apple", "banana", "cherry"};
        System.out.println("Hash code of array1: " + Arrays.hashCode(array1));

        // 对于基本类型数组，使用相应的 hashCode 方法
        int[] numbers = {1, 2, 3};
        System.out.println("Hash code of numbers: " + Arrays.hashCode(numbers));
        // 示例 2 deepHashCode
        // 创建一个二维字符串数组并计算其深哈希码
        String[][] array2D = {{"apple", "banana"}, {"cherry", "date"}};
        System.out.println("Deep hash code of 2D array: " + Arrays.deepHashCode(array2D));

        // 对于更复杂的数据结构，比如包含其他数组的对象数组
        Object[] complexArray = new Object[]{"hello", new Integer[]{1, 2}, new String[]{"a", "b"}};
        System.out.println("Deep hash code of complex array: " + Arrays.deepHashCode(complexArray));

    }

    public static void asList() {
        // 创建一个整数数组
        Integer[] numbers = {1, 2, 3, 4, 5};

        // 将整数数组转换为列表
        List<Integer> list = Arrays.asList(numbers);

        // 打印列表
        System.out.println(list);
    }

    public static void copyOfTest() {
        String[] original = {"Apple", "Banana", "Cherry", "Date"};
        String[] copy = Arrays.copyOf(original, 2); // 复制前两个元素
        System.out.println(Arrays.toString(copy)); // 输出: [Apple, Banana]

        String[] longerCopy = Arrays.copyOf(original, 6); // 原数组长度小于新长度，填充null
        System.out.println(Arrays.toString(longerCopy)); // 输出: [Apple, Banana, Cherry, Date, null, null]
        // copyOfRange
        String[] copyRange = Arrays.copyOfRange(original, 1, 3); // 复制索引1到索引2（不包括索引3）的元素
        System.out.println(Arrays.toString(copyRange)); // 输出: [Banana, Cherry]
    }

    public static void numberSort() {
        // 数字排序
        int[] numbers = {3, 1, 4, 1, 5, 9, 2, 6};
        java.util.Arrays.sort(numbers);
        for (int i : numbers) {
            System.out.print(i + " ");
        }
        System.out.println();
    }

    public static void objectSort() {
        // 对象排序
        String[] strings = {"Hello", "World", "Java"};
        java.util.Arrays.sort(strings);
        for (String s : strings) {
            System.out.print(s + " ");
        }
        System.out.println();
    }


    public static void ParallelSort() {
        // 创建一个随机整数数组
        int[] numbers = {3, 6, 2, 8, 4, 7, 5, 1};

        // 使用 parallelSort 进行排序
        Arrays.parallelSort(numbers);

        // 打印排序后的数组
        System.out.println(Arrays.toString(numbers));
    }

    public static void binarySearch() {
        // 创建一个整数数组
        int[] numbers = {3, 6, 2, 8, 4, 7, 5, 1};

        // 使用 binarySearch 查找元素 5
        int index = Arrays.binarySearch(numbers, 5);

        // 打印查找结果
        System.out.println("元素 5 的索引位置为：" + index);
    }

    public static void fillTest() {
        // 创建一个整型数组并用 7 填充
        int[] numbers = new int[5];
        Arrays.fill(numbers, 7);
        System.out.println("Filled array with 7: " + Arrays.toString(numbers)); // [7, 7, 7, 7, 7]

        // 创建一个字符串数组并用 "hello" 填充
        String[] greetings = new String[3];
        Arrays.fill(greetings, "hello");
        System.out.println("Filled string array: " + Arrays.toString(greetings)); // [hello, hello, hello]

        // 创建一个整型数组并部分填充
        int[] numbers2 = {1, 2, 3, 4, 5};
        Arrays.fill(numbers2, 1, 4, 8); // 从索引 1 到 3（不包括 4）的元素被替换为 8
        System.out.println("Partially filled array: " + Arrays.toString(numbers2)); // [1, 8, 8, 8, 5]

        // 创建一个字符数组并部分填充
        char[] chars = {'a', 'b', 'c', 'd', 'e'};
        Arrays.fill(chars, 2, 5, 'z'); // 从索引 2 到 4（不包括 5）的元素被替换为 'z'
        System.out.println("Partially filled char array: " + Arrays.toString(chars)); // [a, b, z, z, z]
    }

    public static void parallelPrefixTest() {
        // 创建一个整数数组
        int[] numbers = {1, 2, 3, 4, 5};

        // 使用 parallelPrefix 计算数组的前缀和
        Arrays.parallelPrefix(numbers, (left, right) -> left + right);

        // 打印计算结果
        System.out.println(Arrays.toString(numbers));
    }

    public static void equalsTest() {
        int[] array1 = {1, 2, 3};
        int[] array2 = {1, 2, 3};
        int[] array3 = {3, 2, 1};

        // 比较两个相同内容的一维数组
        System.out.println("array1 and array2 are equal: " + Arrays.equals(array1, array2)); // true

        // 比较两个不同顺序的一维数组
        System.out.println("array1 and array3 are equal: " + Arrays.equals(array1, array3)); // false

        // 对于对象类型的数组，比较的是对象的内容（假设实现了正确的 equals 方法）
        String[] stringArray1 = {"hello", "world"};
        String[] stringArray2 = {"hello", "world"};

        System.out.println("stringArray1 and stringArray2 are equal: " + Arrays.equals(stringArray1, stringArray2)); // true


        Integer[][] array4 = {{1, 2}, {3, 4}};
        Integer[][] array5 = {{1, 2}, {3, 4}};
        Integer[][] array6 = {{1, 2}, {4, 3}};

        // 使用 Arrays.deepEquals() 比较两个相同内容的二维数组
        System.out.println("array1 and array2 are deeply equal: " + Arrays.deepEquals(array4, array5)); // true

        // 使用 Arrays.deepEquals() 比较两个不同内容的二维数组
        System.out.println("array1 and array3 are deeply equal: " + Arrays.deepEquals(array4, array6)); // false

        // 对于更复杂的数据结构，比如包含其他数组的对象数组
        Object[] complexArray1 = new Object[]{"hello", new Integer[]{1, 2}, new String[]{"a", "b"}};
        Object[] complexArray2 = new Object[]{"hello", new Integer[]{1, 2}, new String[]{"a", "b"}};

        System.out.println("complexArray1 and complexArray2 are deeply equal: " + Arrays.deepEquals(complexArray1, complexArray2)); // true
    }

}
